const SPLIT_FENCES = [
  [200],
  [300],
  [400],
  [300, 200],
  [300, 300],
  [400, 300],
  [800],
  [900],
  [1000],
  [800, 300],
  [1200],
  [1000, 300],
  [1400],
  [1200, 300],
  [800, 800],
  [900, 800],
  [1000, 800],
  [1000, 900],
  [1000, 1000],
  [1200, 900],
  [1200, 1000],
  [1400, 900],
  [1200, 1200],
  [1200, 1000, 300],
  [1400, 1200],
  [1200, 1200, 300],
  [1400, 1400],
  [1400, 1200, 300]
]

export default {
  getPositionLength: (start: number[], end: number[]) => {
    const x = end[0] - start[0]
    const y = end[1] - start[1]
    return Math.sqrt(x * x + y * y)
  },

  getRealLength: (posLength: number, scale: number) => {
    return Math.round(posLength * scale)
  },

  getAngle: (start: number[], end: number[]) => {
    const diffX = end[0] - start[0]
    const diffY = end[1] - start[1]
    return Math.round((180 / Math.PI) * Math.atan2(diffY, diffX))
  },

  rotatePoint: (x: number, y: number, rad: number) => {
    const rcos = Math.cos(rad)
    const rsin = Math.sin(rad)
    return { x: x * rcos - y * rsin, y: y * rcos + x * rsin }
  },

  fixRadian: (start: number[], angle: number, distance: number) => {
    let radian = 0
    let points = start
    let lineAngle = angle
    if (angle < -180) angle += 360
    if (angle >= -22.5 && angle <= 22.5) {
      lineAngle = 0
      points = start.concat([start[0] + distance, start[1]])
    } else if (angle >= 22.5 && angle <= 67.5) {
      lineAngle = 45
      radian = (45 * Math.PI) / 180
      points = start.concat([
        start[0] + Math.sin(radian) * distance,
        start[1] + Math.cos(radian) * distance
      ])
    } else if (angle >= 67.5 && angle <= 112.5) {
      lineAngle = 90
      points = start.concat([start[0], start[1] + distance])
    } else if (angle >= 112.5 && angle <= 157.5) {
      lineAngle = 135
      radian = (135 * Math.PI) / 180
      points = start.concat([
        start[0] - Math.sin(radian) * distance,
        start[1] - Math.cos(radian) * distance
      ])
    } else if (angle >= 157.5 || angle <= -157.5) {
      lineAngle = 180
      points = start.concat([start[0] - distance, start[1]])
    } else if (angle >= -157.5 && angle <= -112.5) {
      lineAngle = -135
      radian = (-135 * Math.PI) / 180
      points = start.concat([
        start[0] + Math.sin(radian) * distance,
        start[1] + Math.cos(radian) * distance
      ])
    } else if (angle >= -112.5 && angle <= -67.5) {
      lineAngle = -90
      points = start.concat([start[0], start[1] - distance])
    } else if (angle >= -67.5 && angle <= -22.5) {
      lineAngle = -45
      radian = (-45 * Math.PI) / 180
      points = start.concat([
        start[0] - Math.sin(radian) * distance,
        start[1] - Math.cos(radian) * distance
      ])
    }
    return { points, lineAngle }
  },

  getAnglePoints: (start: number[], angle: number, distance: number) => {
    let radian = 0
    let points = start
    if (angle < -180) angle += 360
    if (angle === 0) {
      points = start.concat([start[0] + distance, start[1]])
    } else if (angle > 0 && angle < 90) {
      radian = (angle * Math.PI) / 180
      points = start.concat([
        start[0] + Math.sin(radian) * distance,
        start[1] + Math.cos(radian) * distance
      ])
    } else if (angle === 90) {
      points = start.concat([start[0], start[1] + distance])
    } else if (angle > 90 && angle < 180) {
      radian = (angle * Math.PI) / 180
      points = start.concat([
        start[0] - Math.sin(radian) * distance,
        start[1] - Math.cos(radian) * distance
      ])
    } else if (angle === 180 || angle === -180) {
      points = start.concat([start[0] - distance, start[1]])
    } else if (angle > -180 && angle < -90) {
      radian = (angle * Math.PI) / 180
      points = start.concat([
        start[0] + Math.cos(radian) * distance,
        start[1] + Math.sin(radian) * distance
      ])
    } else if (angle === -90) {
      points = start.concat([start[0], start[1] - distance])
    } else if (angle > -90 && angle < 0) {
      radian = (angle * Math.PI) / 180
      points = start.concat([
        start[0] + Math.cos(radian) * distance,
        start[1] + Math.sin(radian) * distance
      ])
    }
    return points
  },

  fixStartPos: (start: number[], startAngle: number, length: number[], angle: number) => {
    if (startAngle === angle) return [start[0], start[1]]
    switch (angle) {
      case 0:
        return [start[0], start[1]]
      case -45:
        return [start[0] + length[0] / 2, start[1] - length[1] / 2]
      case 45:
        return [start[0] + length[0] / 2, start[1] + length[1] / 2]
      case 90:
        return [start[0], start[1] + length[1]]
      case -90:
        return [start[0], start[1] - length[1]]
      case 180:
        return [start[0] - length[1], start[1]]
      case -180:
        return [start[0], start[1]]
      case 135:
        return [start[0] - length[1] / 2, start[1] - length[0] / 2]
      case -135:
        return [start[0] - length[1] / 2, start[1] - length[0] / 2]
      default:
        return [start[0] + length[0], start[1]]
    }
  },

  splitFence: (length: number) => {
    const spacingCount = Math.ceil(length / 200)
    if (spacingCount <= 4) return [800]
    const fenceCount = Math.ceil(spacingCount / 7)
    const result: number[] = []
    for (let i = 0; i < fenceCount; i++) {
      result.push(800)
    }
    for (let i = 0; i < spacingCount - fenceCount * 4; i++) {
      result[i % fenceCount] = result[i % fenceCount] + 200
    }
    return result
  },

  splitFences: (length: number, lineType: 'minSize' | 'maxSize' = 'minSize') => {
    let result: number[] = []
    let spacingCount = lineType === 'minSize' ? Math.floor(length / 100) : Math.ceil(length / 100)
    if (spacingCount < 2) spacingCount = 2
    const lastPart = spacingCount % 29
    const partCount =
      lineType === 'minSize' ? Math.floor(spacingCount / 29) : Math.ceil(spacingCount / 29)
    for (let i = 0; i < partCount; ) {
      result = result.concat([1400, 1400])
      i += 1
    }

    if (lastPart === 1 && partCount > 0) {
      result.pop()
      result = result.concat([1200, 300])
    } else if (lastPart === 28 && partCount === 0) {
      result = result.concat([1400, 1400])
    } else if (lastPart === 1) {
      result = result.concat(SPLIT_FENCES[0])
    } else if (lastPart > 2 && lastPart < 28) {
      result = result.concat(SPLIT_FENCES[lastPart - 3])
    }
    return result
  },

  splitDoor: (length: number, type: 'JLM' | 'PYM' = 'JLM') => {
    if (type === 'JLM') {
      const spacingCount = Math.ceil(length / 200)

      if (spacingCount <= 4) return [800]
      if (spacingCount <= 7) return [spacingCount * 200]
      const result = [800]
      for (let i = 0; i < spacingCount - 4 && i < 3; ) {
        result[0] += 200
        i += 1
      }
      return result
    }
    const spacingCount = Math.ceil(length / 400)

    if (spacingCount <= 4) return [800 * 2]
    if (spacingCount <= 7) return [spacingCount * 400]
    const result = [1600]
    for (let i = 0; i < spacingCount - 4 && i < 3; ) {
      result[0] += 400
      i += 1
    }
    return result
  }
}
